<?php
/**
 * auth.inc
 * User authoriztion.
 * @copyright	Copyright(c) 2002-2010 Bjorn Winberg
 * @author		Bjorn Winberg <cms@anomalye.net>
 * @license		http://www.gnu.org/licenses/gpl.html GNU General Public License version 2
 * @package		AnomalyWiki
 */
class Auth extends Module{
	public static $MODULE_UID = 'auth';
	const SQL_TABLE_USER = 'CREATE TABLE IF NOT EXISTS auth_user (id INTEGER PRIMARY KEY AUTOINCREMENT, uid TEXT UNIQUE, register_date INTEGER, last_login INTEGER, name TEXT, hash TEXT)';
	const SQL_TABLE_ACTION = 'CREATE TABLE IF NOT EXISTS auth_action (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, security_level INTEGER)';
	const SQL_TABLE_GROUP = 'CREATE TABLE IF NOT EXISTS auth_group (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)';
	const SQL_TABLE_GROUP_ACTION = 'CREATE TABLE IF NOT EXISTS auth_group_action (id INTEGER PRIMARY KEY AUTOINCREMENT, group_id INTEGER, action_id INTEGER)';
	const SQL_TABLE_USER_GROUP = 'CREATE TABLE IF NOT EXISTS auth_user_group (id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER, group_id INTEGER)';
	const PARAM_MAX_ACTION = 64;
	const PARAM_MAX_NAME = 64;
	const PARAM_MAX_ID = 64;
	const PARAM_MAX_PASSWORD = 64;
	const ADMIN_GROUP_ID = 1;
	const USER_GROUP_ID = 2;
	const GUEST_GROUP_ID = 3;
	protected $mSystem;	
	
	/**
	 *
	 */
	public function __construct(){
		parent::__construct();
		$this->loadSettings();
		$this->mSystem = ModuleFactory::loadModule('system');
	}
	
	/**
	 *
	 */
	public function generateView(){
		$params = array();
		$params['db'] = $db = ModuleFactory::getDb();
		if($this->isEmptyUserTable($db)){
			$inputAction = 'register';
		}
		else{
			$inputAction = $this->getParamEnc('a', 1, self::PARAM_MAX_ACTION);
		}
		if($inputAction === 'login'){
			if(!$this->requireAuthorization('AUTH/LOGIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputNameUId = $this->getParamUId('name', 1, self::PARAM_MAX_NAME);
			$inputPassword = $this->getParamEnc('password', 1, self::PARAM_MAX_PASSWORD);
			$params['name'] = $inputNameUId;
			if($inputNameUId !== false && $inputPassword !== false){
				if($this->authorize($db, $inputNameUId, $inputPassword)){
					return $this->generateProfilePage();
				}
			}
			return $this->generateTemplate('auth_login.inc', $params);
		}
		elseif($inputAction === 'profile'){
			return $this->generateProfilePage();
		}
		elseif($inputAction === 'logout'){
			if(!$this->requireAuthorization('AUTH/LOGOUT')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$this->setLoggedSession($db, false);
		}
		elseif($inputAction === 'register'){
			if(!$this->requireAuthorization('AUTH/REGISTER') && !$this->isEmptyUserTable($db)){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputNameDisplay = $this->getParamEnc('name', 1, self::PARAM_MAX_NAME);
			$inputPassword = $this->getParamEnc('password', 1, self::PARAM_MAX_PASSWORD);
			$inputConfirmPass = $this->getParamEnc('confirmpass', 1, self::PARAM_MAX_PASSWORD);
			if($_SERVER['REQUEST_METHOD'] === 'POST'){
				return $this->registerUser($db, $inputNameDisplay, $inputPassword, $inputConfirmPass);
			}
			else{
				return $this->generateTemplate('auth_register.inc', $params);
			}
		}
		elseif($inputAction === 'groups'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputGroupId = $this->getParamEnc('group_id', 1, self::PARAM_MAX_ID);
			$inputUserId = $this->getParamEnc('user_id', 1, self::PARAM_MAX_ID);
			return $this->generatePermissionsPage($db, $inputGroupId, $inputUserId);
		}
		elseif($inputAction === 'add_action'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputActionName = $this->getParamEnc('name', 1, self::PARAM_MAX_NAME);
			if($inputActionName !== false){
				$dbValues = array('name' => $inputActionName, 'security_level' => '1');
				$db->dbExecute('INSERT INTO auth_action' . $db->dbValues($dbValues));
				$this->mSystem->feedbackInfo($this->localString('OK_ADD_ACTION', array($this->getSafeStr($inputActionName))));
				$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_ADD_ACTION', array($this->getSafeStr($inputActionName))));
				return $this->generatePermissionsPage($db, false, false);
			}
		}
		elseif($inputAction === 'delete_action'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputActionId = $this->getParamEnc('action_id', 1, self::PARAM_MAX_ID);
			$result = $db->dbQuery('SELECT * FROM auth_action WHERE id=\'' . $db->dbEscape($inputActionId) . '\'');
			if($row = $result->fetchArray(SQLITE3_ASSOC)){
				$db->dbExecute('DELETE FROM auth_group_action WHERE action_id="' . $db->dbEscape($inputActionId) . '"');
				$db->dbExecute('DELETE FROM auth_action WHERE id="' . $db->dbEscape($inputActionId) . '"');
				$this->mSystem->feedbackInfo($this->localString('OK_DELETE_ACTION', array($this->getSafeStr($row['name']))));
				$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_DELETE_ACTION', array($this->getSafeStr($row['name']))));
				return $this->generatePermissionsPage($db, false, false);
			}
			else{
				$this->mSystem->feedbackWarn($this->localString('ERROR_ACTION_NOT_FOUND'));
				return $this->generatePermissionsPage($db, false, false);
			}
		}
		elseif($inputAction === 'grant_action'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputGroupId = $this->getParamEnc('group_id', 1, self::PARAM_MAX_ID);
			$inputActionId = $this->getParamEnc('action_id', 1, self::PARAM_MAX_ID);
			if($inputActionId !== false && $inputGroupId !== false){	
				$result = $db->dbQuery('SELECT auth_action.name as action_name, auth_group.name as group_name FROM auth_action JOIN auth_group WHERE auth_action.id=\'' . $db->dbEscape($inputActionId) . '\' AND auth_group.id=\'' . $db->dbEscape($inputGroupId) . '\'');
				if($row = $result->fetchArray(SQLITE3_ASSOC)){
					$dbValues = array('action_id' => $inputActionId, 'group_id' => $inputGroupId);
					$db->dbExecute('INSERT INTO auth_group_action' . $db->dbValues($dbValues));
					$this->mSystem->feedbackInfo($this->localString('OK_ADD_GROUP_ACTION', array($this->getSafeStr($row['action_name']), $this->getSafeStr($row['group_name']))));
					$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_ADD_GROUP_ACTION', array($this->getSafeStr($row['action_name']), $this->getSafeStr($row['group_name']))));
					return $this->generatePermissionsPage($db, $inputGroupId, false);
				}
			}
		}
		elseif($inputAction === 'revoke_action'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputGroupId = $this->getParamEnc('group_id', 1, self::PARAM_MAX_ID);
			$inputActionId = $this->getParamEnc('action_id', 1, self::PARAM_MAX_ID);
			if($inputActionId !== false && $inputGroupId !== false){	
				$result = $db->dbQuery('SELECT auth_action.name as action_name, auth_group.name as group_name FROM auth_action JOIN auth_group WHERE auth_action.id=\'' . $db->dbEscape($inputActionId) . '\' AND auth_group.id=\'' . $db->dbEscape($inputGroupId) . '\'');
				if($row = $result->fetchArray(SQLITE3_ASSOC)){
					$dbValues = array('action_id' => $inputActionId, 'group_id' => $inputGroupId);
					$db->dbExecute('DELETE FROM auth_group_action WHERE action_id=\'' . $db->dbEscape($inputActionId) . '\' AND group_id=\'' . $db->dbEscape($inputGroupId) . '\'');
					$this->mSystem->feedbackInfo($this->localString('OK_DELETE_GROUP_ACTION', array($this->getSafeStr($row['action_name']), $this->getSafeStr($row['group_name']))));
					$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_DELETE_GROUP_ACTION', array($this->getSafeStr($row['action_name']), $this->getSafeStr($row['group_name']))));
					return $this->generatePermissionsPage($db, $inputGroupId, false);
				}
			}
		}
		elseif($inputAction === 'add_group'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputGroupName = $this->getParamEnc('name', 1, self::PARAM_MAX_NAME);
			if($inputGroupName !== false){
				$dbValues = array('name' => $inputGroupName);
				$db->dbExecute('INSERT INTO auth_group' . $db->dbValues($dbValues));
				$this->mSystem->feedbackInfo($this->localString('OK_ADD_GROUP', array($this->getSafeStr($inputGroupName))));
				$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_ADD_GROUP', array($this->getSafeStr($inputGroupName))));
				return $this->generatePermissionsPage($db, false, false);
			}
		}
		elseif($inputAction === 'delete_group'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputGroupId = $this->getParamEnc('group_id', 1, self::PARAM_MAX_ID);
			$result = $db->dbQuery('SELECT * FROM auth_group WHERE id=\'' . $db->dbEscape($inputGroupId) . '\'');
			if($row = $result->fetchArray(SQLITE3_ASSOC)){
				$db->dbExecute('DELETE FROM auth_user_group WHERE group_id="' . $db->dbEscape($inputGroupId) . '"');
				$db->dbExecute('DELETE FROM auth_group WHERE id="' . $db->dbEscape($inputGroupId) . '"');
				$this->mSystem->feedbackInfo($this->localString('OK_DELETE_GROUP', array($this->getSafeStr($row['name']))));
				$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_DELETE_GROUP', array($this->getSafeStr($row['name']))));
				return $this->generatePermissionsPage($db, false, false);
			}
			else{
				$this->mSystem->feedbackWarn($this->localString('ERROR_GROUP_NOT_FOUND'));
				return $this->generatePermissionsPage($db, false, false);
			}
		}
		elseif($inputAction === 'join_user'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputGroupId = $this->getParamEnc('group_id', 1, self::PARAM_MAX_ID);
			$inputUserId = $this->getParamEnc('user_id', 1, self::PARAM_MAX_ID);
			if($inputUserId !== false && $inputGroupId !== false){	
				$result = $db->dbQuery('SELECT auth_group.name as group_name, auth_user.name as user_name FROM auth_group JOIN auth_user WHERE auth_group.id=\'' . $db->dbEscape($inputGroupId) . '\' AND auth_user.id=\'' . $db->dbEscape($inputUserId) . '\'');
				if($row = $result->fetchArray(SQLITE3_ASSOC)){
					$dbValues = array('user_id' => $inputUserId, 'group_id' => $inputGroupId);
					$db->dbExecute('INSERT INTO auth_user_group' . $db->dbValues($dbValues));
					$this->mSystem->feedbackInfo($this->localString('OK_ADD_USER_GROUP', array($this->getSafeStr($row['group_name']), $this->getSafeStr($row['user_name']))));
					$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_ADD_USER_GROUP', array($this->getSafeStr($row['group_name']), $this->getSafeStr($row['user_name']))));
					return $this->generatePermissionsPage($db, false, $inputUserId);
				}
			}
		}
		elseif($inputAction === 'kick_user'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputGroupId = $this->getParamEnc('group_id', 1, self::PARAM_MAX_ID);
			$inputUserId = $this->getParamEnc('user_id', 1, self::PARAM_MAX_ID);
			if($inputUserId !== false && $inputGroupId !== false){	
				$result = $db->dbQuery('SELECT auth_group.name as group_name, auth_user.name as user_name FROM auth_user JOIN auth_group WHERE auth_user.id=\'' . $db->dbEscape($inputUserId) . '\' AND auth_group.id=\'' . $db->dbEscape($inputGroupId) . '\'');
				if($row = $result->fetchArray(SQLITE3_ASSOC)){
					$dbValues = array('user_id' => $inputUserId, 'group_id' => $inputGroupId);
					$db->dbExecute('DELETE FROM auth_user_group WHERE user_id=\'' . $db->dbEscape($inputUserId) . '\' AND group_id=\'' . $db->dbEscape($inputGroupId) . '\'');
					$this->mSystem->feedbackInfo($this->localString('OK_DELETE_USER_GROUP', array($this->getSafeStr($row['group_name']), $this->getSafeStr($row['user_name']))));
					$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_DELETE_USER_GROUP', array($this->getSafeStr($row['group_name']), $this->getSafeStr($row['user_name']))));
					return $this->generatePermissionsPage($db, false, $inputUserId);
				}
			}
		}
		elseif($inputAction === 'delete_user'){
			if(!$this->requireAuthorization('AUTH/ADMIN')){
				$this->mSystem->feedbackWarn($this->mSystem->localString('ERROR_PERMISSION_DENIED'));
				return false;
			}
			$inputUserId = $this->getParamEnc('user_id', 1, self::PARAM_MAX_ID);
			$result = $db->dbQuery('SELECT * FROM auth_user WHERE id=\'' . $db->dbEscape($inputUserId) . '\'');
			if($row = $result->fetchArray(SQLITE3_ASSOC)){
				$db->dbExecute('DELETE FROM auth_user_group WHERE user_id="' . $db->dbEscape($inputUserId) . '"');
				$db->dbExecute('DELETE FROM auth_user WHERE id="' . $db->dbEscape($inputUserId) . '"');
				$this->mSystem->feedbackInfo($this->localString('OK_DELETE_USER', array($this->getSafeStr($row['name']))));
				$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_DELETE_USER', array($this->getSafeStr($row['name']))));
				return $this->generatePermissionsPage($db, false, false);
			}
			else{
				$this->mSystem->feedbackWarn($this->localString('ERROR_GROUP_NOT_FOUND'));
				return $this->generatePermissionsPage($db, false, false);
			}
		}
	}
	
	/**
	 *
	 */
	public function registerUser($aDb, $aNameDisplay, $aPassword, $aConfirmPass){
		$params['db'] = ModuleFactory::getDb();
		$aNameUId = strtolower($aNameDisplay);
		$superGroupId = false;
		if($this->isEmptyUserTable($aDb)){
			if($this->getParamEnc('install_password', 1, self::PARAM_MAX_PASSWORD) !== $this->localSetting('INSTALL_PASSWORD')){
				$this->mSystem->feedbackWarn($this->localString('ERROR_INSTALL_PASSWORD'));
				return $this->generateTemplate('auth_register.inc', $params);
			}
			else{
				$loginId = $this->addAction($aDb, rawurlencode('AUTH/LOGIN'), 1);
				$logoutId = $this->addAction($aDb, rawurlencode('AUTH/LOGOUT'), 1);
				$registerId = $this->addAction($aDb, rawurlencode('AUTH/REGISTER'), 1);
				$adminId = $this->addAction($aDb, rawurlencode('AUTH/ADMIN'), 1);
				$superGroupId = $this->addGroup($aDb, rawurlencode('Admin'), self::ADMIN_GROUP_ID);
				assert($superGroupId === self::ADMIN_GROUP_ID);
				$userId = $this->addGroup($aDb, rawurlencode('User'), self::USER_GROUP_ID);
				assert($userId === self::USER_GROUP_ID);
				$guestId = $this->addGroup($aDb, rawurlencode('Guest'), self::GUEST_GROUP_ID);
				assert($guestId === self::GUEST_GROUP_ID);
				$this->grantAction($aDb, $guestId, $loginId);
				$this->grantAction($aDb, $guestId, $registerId);
				$this->grantAction($aDb, $userId, $logoutId);
				$this->grantAction($aDb, $superGroupId, $logoutId);
				$this->grantAction($aDb, $superGroupId, $adminId);
				$this->grantGroup($aDb, false, $guestId);
				ModuleFactory::loadModule('logs');
				ModuleFactory::loadModule('menueditor');
				ModuleFactory::loadModule('settings');
				ModuleFactory::loadModule('article');
				$this->setLoggedSession($aDb, false);
			}
		}
		if($aNameDisplay === false || $aPassword === false || $aConfirmPass === false){
			$this->mSystem->feedbackWarn($this->localString('ERROR_INPUT_FAIL'));
			return $this->generateTemplate('auth_register.inc', $params);
		}
		if($aPassword !== $aConfirmPass){
			$this->mSystem->feedbackWarn($this->localString('ERROR_PASS_CONFIRM'));
			return $this->generateTemplate('auth_register.inc', $params);
		}
		$result = $aDb->dbQuery('SELECT * FROM auth_user WHERE uid=\'' . $aDb->dbEscape($aNameUId) . '\'');
		if($row = $result->fetchArray(SQLITE3_ASSOC)){ 
			$this->mSystem->feedbackWarn($this->localString('ERROR_NAME_TAKEN'));
			return $this->generateTemplate('auth_register.inc', $params);
		}
		else{
			$time = time();
			$saltedHash =  bin2hex(mhash(MHASH_SHA1, $aPassword, $time));
			$dbValues = array('uid' => $aNameUId, 'register_date' => $time, 'last_login' => $time, 'name' => $aNameDisplay, 'hash' => $saltedHash);
			$aDb->dbExecute('INSERT INTO auth_user' . $aDb->dbValues($dbValues));
			$userId = $aDb->dbLastId();
			$this->grantGroup($aDb, $userId, self::USER_GROUP_ID);
			if($superGroupId !== false){
				$this->grantGroup($aDb, $userId, $superGroupId);
			}
			$this->mSystem->feedbackInfo($this->localString('OK_REGISTER'));
			$this->mSystem->feedbackLog(static::$MODULE_UID, $this->localString('LOG_REGISTER', array($this->getSafeStr($aNameDisplay))));
			return 'ToDo';
		}
	}
	
	/**
	 *
	 */
	public function generatePermissionsPage($aDb, $aGroupId, $aUserId){
		$params['users'] = array();
		$sqlPageSize = $this->localSetting('USERS_PAGE_SIZE') + 1;
		if($aGroupId !== false){
			$userResult = $aDb->dbQuery('SELECT auth_user_group.user_id as id, auth_user.name as name FROM auth_user_group JOIN auth_user WHERE auth_user.id=auth_user_group.user_id AND auth_user_group.group_id=\'' . $aDb->dbEscape($aGroupId) . '\' LIMIT ' . $aDb->dbEscape($sqlPageSize) . ' OFFSET ' . $aDb->dbEscape($this->pagingOffset()));
			$usersBaseUrl = $this->generateUrl('auth', array('a' => 'groups', 'group_id' => $aGroupId));
		}
		else{
			$userResult = $aDb->dbQuery('SELECT * FROM auth_user LIMIT ' . $aDb->dbEscape($sqlPageSize) . ' OFFSET ' . $aDb->dbEscape($this->pagingOffset()));
			$usersBaseUrl = $this->generateUrl('auth', array('a' => 'groups'));
		}
		$selectCount = 0;
		while($userRow = $userResult->fetchArray(SQLITE3_ASSOC)){ 
			if($selectCount < $this->localSetting('USERS_PAGE_SIZE')){
				$params['users'][$userRow['id']] = $userRow['name'];
			}
			$selectCount++;
		}
		$params['usersNext'] = $this->pagingNextUrl($usersBaseUrl, $this->localSetting('USERS_PAGE_SIZE'), $selectCount);
		$params['usersPrev'] = $this->pagingPrevUrl($usersBaseUrl, $this->localSetting('USERS_PAGE_SIZE'));
		
		$groupResult = $aDb->dbQuery('SELECT * FROM auth_group');
		$params['groups'] = array();
		while($groupRow = $groupResult->fetchArray(SQLITE3_ASSOC)){ 
			$params['groups'][$groupRow['id']] = $groupRow['name'];
		}
		
		$actionResult = $aDb->dbQuery('SELECT * FROM auth_action');
		$params['actions'] = array();
		while($actionRow = $actionResult->fetchArray(SQLITE3_ASSOC)){ 
			$params['actions'][$actionRow['id']] = $actionRow['name'];
		}
		
		$params['groupName'] = false;
		$params['groupId'] = false;
		$params['groupActions'] = array();
		if($aGroupId !== false){
			$params['groupName'] = $params['groups'][$aGroupId];
			$params['groupId'] = $aGroupId;
			$groupActionResult = $aDb->dbQuery('SELECT * FROM auth_group_action JOIN auth_action WHERE auth_action.id=auth_group_action.action_id AND auth_group_action.group_id=\'' . $aDb->dbEscape($aGroupId) . '\'');
			while($groupActionRow = $groupActionResult->fetchArray(SQLITE3_ASSOC)){ 
				$params['groupActions'][$groupActionRow['action_id']] = $groupActionRow['name'];
			}
		}
		
		$params['userName'] = false;
		$params['userId'] = false;
		$params['userGroups'] = array();
		$params['userGroupActions'] = array();
		if($aUserId !== false){
			$userLookupResult = $aDb->dbQuery('SELECT * FROM auth_user WHERE id=\'' . $aDb->dbEscape($aUserId) . '\'');
			if($userLookupRow = $userLookupResult->fetchArray(SQLITE3_ASSOC)){ 
				$params['userName'] = $userLookupRow['name'];
				$params['userId'] = $aUserId;
				$userGroupResult = $aDb->dbQuery('SELECT * FROM auth_user_group JOIN auth_group WHERE auth_group.id=auth_user_group.group_id AND auth_user_group.user_id=\'' . $aDb->dbEscape($aUserId) . '\'');
				while($userGroupRow = $userGroupResult->fetchArray(SQLITE3_ASSOC)){ 
					$params['userGroups'][$userGroupRow['group_id']] = $userGroupRow['name'];
				}
				$userGroupActionsResult = $aDb->dbQuery('SELECT auth_group_action.action_id as id, auth_group.name as name FROM auth_user_group JOIN auth_group,auth_group_action WHERE auth_user_group.group_id=auth_group_action.group_id AND auth_group.id=auth_group_action.group_id AND auth_user_group.user_id=\'' . $aDb->dbEscape($aUserId) . '\'');
				while($userGroupActionRow = $userGroupActionsResult->fetchArray(SQLITE3_ASSOC)){ 
					$params['userGroupActions'][$userGroupActionRow['id']][] = $userGroupActionRow['name'];
				}
			}
		}
		return $this->generateTemplate('auth_groups.inc', $params);
	}
	
	/**
	 *
	 */
	public function generateProfilePage(){
		$params['name'] = $_SESSION['auth']['user']['name'];
		return $this->generateTemplate('auth_userPage.inc', $params);
	}
	
	/**
	 *
	 */
	public function firstTimeSetup(){
		$db = ModuleFactory::getDb();
		$db->dbExecute(self::SQL_TABLE_USER);
		$db->dbExecute(self::SQL_TABLE_ACTION);
		$db->dbExecute(self::SQL_TABLE_GROUP);
		$db->dbExecute(self::SQL_TABLE_GROUP_ACTION);
		$db->dbExecute(self::SQL_TABLE_USER_GROUP);
	}
	
	/**
	 *
	 */
	public function isEmptyUserTable($aDb){
		$result = $aDb->dbQuery('SELECT count(*) AS count FROM auth_user');
		$row = $result->fetchArray(SQLITE3_ASSOC);
		if($row['count'] === 0){
			return true;
		}
		return false;
	}
	
	/**
	 *
	 */
	public function addAction($aDb, $aActionName, $aLevel){
		$dbValues = array('name' => $aActionName, 'security_level' => $aLevel);
		$aDb->dbExecute('INSERT INTO auth_action' . $aDb->dbValues($dbValues));
		return $aDb->dbLastId();
	}
	
	/**
	 *
	 */
	public function addGroup($aDb, $aGroupName, $aGroupId = false){
		if($aGroupId !== false){
			$dbValues = array('name' => $aGroupName, 'id' => $aGroupId);
		}
		else{
			$dbValues = array('name' => $aGroupName);
		}
		$aDb->dbExecute('INSERT INTO auth_group' . $aDb->dbValues($dbValues));
		return $aDb->dbLastId();
	}
	
	/**
	 *
	 */
	public function grantAction($aDb, $aGroupId, $aActionId){
		$dbValues = array('group_id' => $aGroupId, 'action_id' => $aActionId);
		$aDb->dbExecute('INSERT INTO auth_group_action' . $aDb->dbValues($dbValues));
		return $aDb->dbLastId();
	}
	
	/**
	 *
	 */
	public function grantGroup($aDb, $aUserId, $aGroupId){
		$dbValues = array('user_id' => $aUserId, 'group_id' => $aGroupId);
		$aDb->dbExecute('INSERT INTO auth_user_group' . $aDb->dbValues($dbValues));
		return $aDb->dbLastId();
	}
		
	/**
	 *
	 */
	function authorize($aDb, $aUserUId, $aPassword){
		$result = $aDb->dbQuery('SELECT * FROM auth_user WHERE uid=\'' . $aDb->dbEscape($aUserUId) . '\'');
		if($row = $result->fetchArray(SQLITE3_ASSOC)){ 
			$saltedHash =  bin2hex(mhash(MHASH_SHA1, $aPassword, $row['register_date']));
			if($saltedHash == $row['hash']){
				$timescript = $this->mSystem->generateTimeScript($row['last_login']);
				$this->mSystem->feedbackInfo($this->localString('OK_LOGIN', array($this->getSafeStr($row['name']), $timescript)));
				$this->setLoggedSession($aDb, $row);
				return true;
			}
			else{
				$this->mSystem->feedbackWarn($this->localString('ERROR_LOGIN'));
			}
		}
		else{
			$this->mSystem->feedbackWarn($this->localString('ERROR_LOGIN'));
		}
		return false;
	}
	
	/**
	 * 
	 */
	function setLoggedSession($aDb, $aUserItem){
		session_regenerate_id(true);
		$_SESSION['auth'] = false;
		$time = time();
		if($aUserItem === false){
			$_SESSION['auth']['user']['id'] = false;
			$_SESSION['auth']['user']['name'] = false;
			$_SESSION['auth']['user']['last_login'] = $time;
		}
		else{
			unset($aUserItem['hash']);
			$_SESSION['auth']['user'] = $aUserItem;
			$aDb->dbExecute('UPDATE auth_user SET last_login="' . $aDb->dbEscape($time) . '" WHERE uid="' . $aDb->dbEscape($aUserItem['uid']) . '"');
		}
		$userGroupResult = $aDb->dbQuery('SELECT * FROM auth_user_group JOIN auth_group_action, auth_action WHERE auth_user_group.group_id = auth_group_action.group_id AND auth_action.id = auth_group_action.action_id AND auth_user_group.user_id=\'' . $aDb->dbEscape($_SESSION['auth']['user']['id']) . '\'');
		while($userGroupRow = $userGroupResult->fetchArray(SQLITE3_ASSOC)){ 
			$actionBits = explode('_', $userGroupRow['name']);
			$bitCount = count($actionBits);
			$_SESSION['auth']['user']['actions'][$actionBits[0]] = array();
			for($i = 1; $i < $bitCount; $i++){
				$_SESSION['auth']['user']['actions'][$actionBits[0]][$actionBits[$i]] = true;
			}
		}
	}
}
?>
